﻿using System;
using System.Collections.Generic;

namespace Bricks.Injecting
{

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TService"></typeparam>
    public abstract class ValueResolverBase<TService> : IValueResolver<TService>
    {

        /// <summary>
        /// 
        /// </summary>
        private readonly Func<TService> _valueAccessor;

        /// <summary>
        /// 
        /// </summary>
        private readonly Func<TService> _defaultValueAccessor;

        /// <summary>
        /// 
        /// </summary>
        private readonly object _syncRoot = new object();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="valueAccessor"></param>
        /// <param name="defaultValueAccessor"></param>
        protected ValueResolverBase(Func<TService> valueAccessor, Func<TService> defaultValueAccessor)
        {
            if (valueAccessor == null)
            {
                throw new ArgumentNullException("valueAccessor");
            }
            if (defaultValueAccessor == null)
            {
                throw new ArgumentNullException("defaultValueAccessor");
            }

            _valueAccessor = valueAccessor;

            _defaultValueAccessor = defaultValueAccessor;
        }

        /// <summary>
        /// 
        /// </summary>
        protected Object SyncRoot
        {
            get { return _syncRoot; }
        }

        /// <summary>
        /// 
        /// </summary>
        protected virtual TService Value
        {
            get { try { return _valueAccessor.Invoke(); } catch { return default(TService); } }
        }

        /// <summary>
        /// 
        /// </summary>
        protected virtual TService DefaultValue
        {
            get { try { return _defaultValueAccessor.Invoke(); } catch { return default(TService); } }
        }

        /// <summary>
        /// 
        /// </summary>
        public virtual TService Resolve()
        {
            lock (SyncRoot)
            {
                TService value = Value;

                return EqualityComparer<TService>.Default.Equals(value, default(TService)) ? DefaultValue : value;
            }
        }
    }
}
